PROJECT = "smartpet_data_algorithm"
VERSION = "0.0.5"

-- sys库是标配
sys = require "sys"

local aht10 = require "aht10"
local adxl34x = require "adxl346" --需要适配调试的三个传感器接口，具体参考aht10.lua内容
local mpu6xxx = require "mpu6050"
local max30102 = require "max30102_old"

require "basic"

aht10_i2cid = 1  --i2c用于aht10
aht10_i2c_speed = i2c.FAST
adxl346_i2cid = 2
mpu6050_i2cid = 3
max30102_i2cid = 0

spi_lcd = spi.deviceSetup(2, 7, 0, 0, 8, 40000000, spi.MSB, 1, 1)  --spi用于aht10

lcd.init("st7735v",{port = "device",pin_dc = 6, pin_pwr = 11,pin_rst = 10,direction = 1,w = 160,h = 80,xoffset = 0,yoffset = 24},spi_lcd)
--如果显示颜色相反，关闭反色
lcd.invoff()

notif = " "  --LED文字信息

--aht10_data=nil
max30102_data={}
change=false  --标记采集到新数据
dbg=0  --标记是否调试

network = 2  --标记当前是否使用网络，0不使用，1使用，2等待确认

wlan_id="OPPO K5"
wlan_password="12345678"

server_ip="192.168.47.32"
server_port=6666
server_id="server"
server_ctrl=nil
rx_buff=zbuff.create(1024)


local function netCB(netc, event, param)
    if param ~= 0 then
        sys.publish("socket_disconnect")
        return
    end
	if event == socket.LINK then
	elseif event == socket.ON_LINE then
        --socket.tx(netc, "hello,luatos!")
	elseif event == socket.EVENT then
        --rx_buff=zbuff.create(1024)
        --socket.rx(netc, rx_buff)
        --socket.wait(netc)
        --if rx_buff:used() > 0 then
        --    log.info("收到", rx_buff:toStr(0,rx_buff:used()):toHex())
        --    --log.info("发送", rx_buff:used(), "bytes")
        --    --socket.tx(netc, rx_buff)
        --end
        --rx_buff:del()
	elseif event == socket.TX_OK then
        --socket.wait(netc)
        log.info("发送完成")
	elseif event == socket.CLOSE then
        sys.publish("socket_disconnect")
    end
end

function tcplink()
    log.info("socket", "begin socket")
    local ret = 0
    while 1 do
        rx_buff=zbuff.create(1024)
        server_ctrl=socket.create(nil, netCB)
        --socket.debug(server_ctrl, true)
        socket.config(server_ctrl, nil, false, false)
        log.info("socket.init", server_ctrl, server_id)

        --sock = socket.create(socket.TCP)  --tcp  old
        --log.info('socket.create_ock:',sock)  --old
        while 1 do
            -- 根据需要连接的服务器写, 第4个参数启用非阻塞（试了，似乎没用所以删了）
            -- 注意不能填127.0.0.1, 如果是连接电脑的端口, 填电脑的局域网ip
            --cw = socket.connect(sock, "192.168.86.32", 1234)  --old
            local succ, result=socket.connect(server_ctrl,server_ip,server_port)
            if succ then
                log.info("socket.connect", "connected", ret, succ, result)
                sys.waitUntil("socket_disconnect")
                break
            else
                log.info("socket.connect", "connect timeout", ret, succ, result)
                ret=ret+1
                socket.close(server_ctrl)
                --socket.close(sock)  --old
                sys.wait(100)
                --sock = socket.create(socket.TCP)  --old
            end
            sys.wait(3000)  -- 重试间隔
        end

        --len = socket.send(sock, "connected\n")  --old
        local result,param=socket.tx(server_ctrl, "connected\n")
        log.info("socket_send", "result : ", result, param)
        local succ,param2=socket.rx(server_ctrl, rx_buff)
        log.info("socket_receive", "result : ", succ, param2)

        -- 若发送失败, 下面的逻辑就直接跳过了
        --local counter = 0
        while result and succ do
            -- recv是非阻塞, 会马上返回

            --local data, len = socket.recv(sock)  --old
            local len, data=rx_buff:used(), rx_buff:query()
            -- 若data存在, 且长度大于0, 那就是真的收到数据了
            rx_buff:del()

            --if change then  --数据有更新才发送
            --    socket.send(sock, string.format("%0.5f%%,%0.5f℃\n",aht10_data.RH*100,aht10_data.T))
            --    change=false
            --end

            if gpio.get(9)==0 then  --若连接中按下BOOT则断开连接关闭wifi
                log.info("socket", "server close")
                network=0
                break
            end

            if data ~= nil and len > 0 then
                -- 这里是演示服务器下发close字符串
                if data == "close" then
                    log.info("socket", "server say","close")
                    break -- 退出循环, 在后续代码中关闭close
                end
                log.info("socket_receive", "len : ", len)
                log.info("socket_receive", "data : ", data)
            -- 若 len 小于 0, 带代表出错, socket关掉之
            elseif len and len < 0 then
                log.info("socket", "closed")
                break
            end
            --[[ 这里模拟一下心跳（暂时没用）
            if len and len == 0 then
                -- 没数据, 就需要心跳计数
                counter = counter + 1
            else
                -- 有数据就不需要心跳了
                counter = 0
            end
            if counter > 100 then
                counter = 0
                len = socket.send(sock, "my heartbeat")
            end]]
            sys.wait(50) -- 延时是为了让出cpu给其他task, 建议大于10ms
        end
        -- 关闭socket,清理资源
        --socket.close(sock)  --old
        socket.close(server_ctrl)
        collectgarbage("collect")
        collectgarbage("collect")
        log.info("socket", "end")
        if network==0 then
            wlan.disconnect()
            notif='disconnected'
            break
        end
        sys.wait(2000) -- 2000ms后重连
        
    end
end

function send_data(tag, data, len)
    socket.tx(server_ctrl, string.format("%s\n%d\n",tag,len))
    if tag=='batch' then
        socket.tx(server_ctrl, string.format("%d\n",data[1]))
        for i=2,len do
            socket.tx(server_ctrl, string.format("%f\n",data[i]))
        end
    else
        for i=1,len do
            --if tag=='ir_d2' then
            --    log.debug('ir_d2',i,data[i],data[i+1],string.format("  %d",data[i]))
            --end
            if tag=='temp_r' then
                socket.tx(server_ctrl, string.format("%f\n",data[i]))
            else
                socket.tx(server_ctrl, string.format("%d\n",data[i]))
            end
            
            --if tag=='ir_d2' then
            --    socket.tx(server_ctrl, string.format("44\n"))
            --elseif tag=='ir_d' then
            --    socket.tx(server_ctrl, string.format("33\n"))
            --elseif tag=='ir_p' then
            --    socket.tx(server_ctrl, string.format("22\n"))
            --elseif tag=='ir_r' then
            --    socket.tx(server_ctrl, string.format("11\n"))
            --end
            --if i % 10 ==0 then
            --    log.info("sent ###.",tag,i)
            --end
        end    
    end
    while 1 do
        local succ, param2=socket.rx(server_ctrl, rx_buff)
        local len, data=rx_buff:used(), rx_buff:query()
        rx_buff:del()
        --log.info("send",succ,param2,len,data)
        if len==3 then
            log.info("send.success",succ,param2,len,data)
            break
        end
    end
    sys.publish(tag)
end

function wlan_init()
    network=1
    log.info("wlan", "wlan_init:", wlan.init())
    wlan.setMode(wlan.STATION)

    --WIFI扫描和中继测试，中继有问题还没实现
    --wlan.scan()
    --sys.waitUntil("WLAN_SCAN_DONE", 5000)
    --local re = wlan.scanResult()
    --local wifilist ={}
    --for i in ipairs(re) do
    --    table.insert(wifilist,string.format("%s###\n",re[i].ssid))
    --    --wifilist=wifilist..string.format("%s;%s###\n",re[i].ssid)
    --end
    --table.concat(wifilist)
    --log.info("wlan.info",wifilist[1])
    --log.info("wlan.scan_done")
    
    --log.info("wlan.createAP", wlan.createAP("c3-luatos", "12345678"))
    --log.info("wlan.dhcp", wlan.dhcp(0)) -- 关闭dhcp
    --log.info("wlan.setip", wlan.setIp("192.168.55.1", "192.168.55.1", "255.255.255.0"))
    --log.info("wlan.dhcp", wlan.dhcp(1)) -- 开启dhcp

    wlan.connect(wlan_id, wlan_password, 1) --我的手机热点
    result, _ = sys.waitUntil("WLAN_STA_CONNECTED")
    log.info("wlan", "WLAN_STA_CONNECTED", result)
    while 1 do
        result, data = sys.waitUntil("IP_READY", 10000)
        log.info("wlan", "IP_READY", result, data)
        notif=string.format("IP:%s",data)
        -- 若result == true, 代表wifi连接成功了
        -- data 是 本地ip, 可按自身业务存储
        if result then
            break
        end
    end

    --WIFI中继测试，有问题还没实现
    --log.info("wlan.createAP", wlan.createAP("c3-luatos", "12345678"))
    --log.info("wlan.dhcp", wlan.dhcp(0)) -- 关闭dhcp
    --log.info("wlan.setip", wlan.setIp("192.168.55.1", "192.168.55.1", "255.255.255.0"))
    --log.info("wlan.dhcp", wlan.dhcp(1)) -- 开启dhcp

    --log.info("wlan.connect.bw",wlan.getBandwidth(wlan.IF_STA))
    --log.info("wlan.ap.bw",wlan.getBandwidth(wlan.IF_AP))

    --sysplus.taskInitEx(tcplink,server_id,netCB)
    sys.taskInit(tcplink)  --old

end

function query_wifiopen()
    notif="Disable Wifi?"
    if gpio.get(9)==0 then
        notif="offline"
        network=0
        return true
    end
    return false
end

sys.taskInit(
    function()
        --i2c.setup(aht10_i2cid,aht10_i2c_speed)
        --aht10.init(aht10_i2cid)--初始化,传入i2c_id

        adxl346_i2cid=i2c.createSoft(8,9,0x53)
        log.info("adxl346_i2cid:",adxl346_i2cid)
        --log.info("setup_adxl346",i2c.setup(adxl346_i2cid,i2c.FAST,0x53))
        adxl34x.init(adxl346_i2cid)

        --max30102_i2cid=i2c.createSoft(18,19,MAX30102_ADDRESS)
        log.info("setup_max30102",i2c.setup(max30102_i2cid,i2c.FAST,0x57))
        log.info("max30102_i2cid:",max30102_i2cid)
        max30102.setup(max30102_i2cid)

        log.info("lcd.clear", lcd.clear(0xFFFE))
        log.info("lcd.setfont",lcd.setFont(lcd.font_opposansm8))

        sys.taskInit(waitloopmoudle)  --运行计时模块
        gpio.setup(9,nil)

        lcd.fill(0, 0, 160, 80,0x11FE)  --蓝背景提示
        addwaitloop(query_wifiopen,nil,wlan_init,nil,3)  --开头是否启用wifi，3秒内按下boot即不启用

        while notif=="Disable Wifi?" or notif==" " do
            sys.wait(50)
        end
        --log.info("wlan.close","yes!",network)

        while 1 do
            --aht10_data = aht10.get_data()
            --adxl346_data = adxl34x.get_data()  --本库待进一步调试
            --mpu6050_data = mpu6050.get_data()  --需要适配调试的三个传感器接口，具体参考aht10.lua内容
            --max30102_pre_data = max30102.get_pre_data()  --old
            --max30102_spo2 = max30102.get_spo2(50)  --old
            --log.info("max30102.get","no!")
            max30102_data = max30102.get_rate_and_spo2()
            local batch_data={}
            local batch_len=10
            batch_data[1]=max30102_data.valid
            batch_data[2]=max30102_data.temp
            batch_data[3]=max30102_data.rate
            batch_data[4]=max30102_data.spo2
            for i=5,batch_len do
                batch_data[i]=adxl34x.get_a()
                log.info('acc',batch_data[i])
            end

            change=true
            --log.info("max30102.get","yes!")

            --local adc_data,_=adc.read(0)
            --log.info("adc",adc_data/4096*3.3,"V")

            --log.info("aht10_data", "aht10_data.RH:"..(aht10_data.RH*100).."%","  aht10_data.T:"..(aht10_data.T).."℃"," Data1:",aht10_data.d1)
            --log.info("adxl346_data", "adxl346_data.x:"..(adxl346_data.x),"  adxl346_data.y:"..(adxl346_data.y),"  adxl346_data.z:"..(adxl346_data.z))
            --log.info("max30102_pre_data", "max30102_pre_data.ir:"..(max30102_pre_data.ir),"  max30102_pre_data.red:"..(max30102_pre_data.red)) --弃用
            --log.info("max30102_spo2", "max30102_spo2:"..(max30102_spo2).."%") --弃用
            log.info("max30102_spo2","max30102_suc:"..(max30102_data.valid).. "; max30102_rate:"..(max30102_data.rate).. "; max30102_spo2:"..(max30102_data.spo2).."%")
            lcd.fill(0, 0, 160, 80,0xFFFE)
            lcd.drawStr(20,10,notif)
            --lcd.drawStr(20,40,string.format("%0.5f%%,%0.5fC",aht10_data.RH*100,aht10_data.T))
            --lcd.drawStr(10,50,string.format("x:%d,y:%d,z:%d",adxl346_data.x,adxl346_data.y,adxl346_data.z))
            --lcd.drawStr(20,50,string.format("%0.5f%%",max30102_pre_data.red)) --弃用
            if max30102_data.valid==1 then
                lcd.drawStr(20,40,"VALID.")
            else
                lcd.drawStr(20,40,"INVALID. Please check.")
            end
            lcd.drawStr(20,50,string.format("%d bpm;  %0.3f%%",math.floor(max30102_data.rate),max30102_data.spo2))
            lcd.drawStr(20,60,string.format("%0.3fC",max30102_data.temp))
            if dbg==0 and network==1 then
                send_data("batch",batch_data,batch_len)
                sys.waitUntil("batch",1000)
            end
            sys.wait(500)  --间隔500ms再采样
        end
    end
)

-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!